package org.hepeng.workx.util.reflect;

import org.apache.commons.lang3.StringUtils;
import org.hepeng.workx.util.ClassPathUtils;
import org.hepeng.workx.util.concurrent.NamedThreadFactory;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ConfigurationBuilder;

import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author he peng
 */
public class ReflectionsUtils {

    private static Reflections allClassReflections;
    private static Future<Reflections> allClassReflectionsFuture;

    static {
        ThreadFactory threadFactory = new NamedThreadFactory("reflections-load-class" , true);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1 , 1 , 0L , TimeUnit.MILLISECONDS , new LinkedBlockingQueue<>() , threadFactory);

        allClassReflectionsFuture = executor.submit(new Callable<Reflections>() {
            @Override
            public Reflections call() throws Exception {
                ConfigurationBuilder config = new ConfigurationBuilder();
                config.setInputsFilter(input -> StringUtils.endsWith(input, ".class"));
                config.addUrls(ClassPathUtils.forJavaClassPath());
                config.forPackages("");
                config.setExpandSuperTypes(true);
                config.addScanners(new SubTypesScanner());
                allClassReflections = new Reflections(config);
                return allClassReflections;
            }
        });
    }

    public static Reflections getAllClassReflections() {
        return allClassReflections;
    }
}
